package com.atguigu.gulimall.product.service.impl;

import com.atguigu.common.constant.ProductConstant;
import com.atguigu.common.utils.PageUtils;
import com.atguigu.common.utils.Query;
import com.atguigu.gulimall.product.dao.AttrDao;
import com.atguigu.gulimall.product.entity.AttrAttrgroupRelationEntity;
import com.atguigu.gulimall.product.entity.AttrEntity;
import com.atguigu.gulimall.product.entity.AttrGroupEntity;
import com.atguigu.gulimall.product.entity.CategoryEntity;
import com.atguigu.gulimall.product.service.AttrAttrgroupRelationService;
import com.atguigu.gulimall.product.service.AttrGroupService;
import com.atguigu.gulimall.product.service.AttrService;
import com.atguigu.gulimall.product.service.CategoryService;
import com.atguigu.gulimall.product.vo.AttrGroupRelationVo;
import com.atguigu.gulimall.product.vo.AttrResponseVo;
import com.atguigu.gulimall.product.vo.AttrVo;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.additional.query.impl.QueryChainWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.*;
import java.util.stream.Collectors;


@Service("attrService")
public class AttrServiceImpl extends ServiceImpl<AttrDao, AttrEntity> implements AttrService {

    @Resource
    private AttrAttrgroupRelationService aars;
    @Resource
    private AttrGroupService attrGroupService;
    @Resource
    private CategoryService categoryService;

    @Override
    public PageUtils queryPage(Map<String, Object> params) {
        IPage<AttrEntity> page = this.page(
                new Query<AttrEntity>().getPage(params),
                new QueryWrapper<AttrEntity>()
        );

        return new PageUtils(page);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void saveAttr(AttrVo attr) {
        // 1.获得分组ID
        Long attrGroupId = attr.getAttrGroupId();
        // 2.保存属性信息
        AttrEntity attrEntity = new AttrEntity();
        BeanUtils.copyProperties(attr, attrEntity);
        this.save(attrEntity);
        if (attr.getAttrType() == ProductConstant.AttrEnum.ATTR_TYPE_BASE.getCode()
                && attr.getAttrGroupId() != null) {
            // 3.保存分组和属性的关联关系
            AttrAttrgroupRelationEntity are = new AttrAttrgroupRelationEntity();
            // 拿到属性保存之后的ID
            are.setAttrId(attrEntity.getAttrId());
            are.setAttrGroupId(attrGroupId);
            aars.save(are);
        }
    }

    @Override
    public PageUtils queryBaseAttrPage(Map<String, Object> params, Long catelogId, String type) {
        // 1.type：销售属性 和 基本属性
        QueryWrapper<AttrEntity> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("attr_type",
                "base".equalsIgnoreCase(type) ? ProductConstant.AttrEnum.ATTR_TYPE_BASE.getCode()
                        : ProductConstant.AttrEnum.ATTR_TYPE_SALE.getCode());
        // 2.key属性 全局模糊查询(ID和组名)
        String key = (String) params.get("key");
        // 3.如果有模糊查询
        if (StringUtils.isNotEmpty(key)) {
            queryWrapper.and(obj -> {
                obj.eq("attr_id", key).or()
                        .like("attr_name", key);
            });
        }
        // 4.如果分类ID为0，则查所有,不是则查对应分类下的 属性
        if (!Objects.equals(catelogId, ProductConstant.CategoryEnum.CATEGORY_ID.getCode())) {
            queryWrapper.and((wrapper) -> {
                wrapper.eq("catelog_id", catelogId);
            });
        }
        /** 5.查询出所有的信息,
         *  SELECT COUNT(1) FROM pms_attr WHERE (attr_type = ? AND ((catelog_id = ?)))
         *  会先查询是否有数据，没有直接下一步，有，再发SQL语句
         * */
        IPage<AttrEntity> page = this.page(
                new Query<AttrEntity>().getPage(params),
                queryWrapper
        );
        // 6.将查询到的信息封装到PageUtils
        PageUtils pageUtils = new PageUtils(page);
        List<?> list = pageUtils.getList();
        // 7.组装该规格参数是哪个 分组下的 和 分类下的
        List<AttrResponseVo> voList = list.stream().map((attrEntity) -> {
            // 7.1将数据封装到AttrResponseVo
            AttrResponseVo attrRespVo = new AttrResponseVo();
            BeanUtils.copyProperties(attrEntity, attrRespVo);
            // 7.2根据规格参数ID获取 参数对应的 分组
            AttrAttrgroupRelationEntity attrGroupRelation = aars.getOne(
                    new QueryWrapper<AttrAttrgroupRelationEntity>()
                            .eq("attr_id", attrRespVo.getAttrId()));

            if ("base".equalsIgnoreCase(type)) {
                // 获取该规格参数对应的 分组名称
                if (null != attrGroupRelation && null != attrGroupRelation.getAttrGroupId()) {
                    QueryWrapper<AttrGroupEntity> groupWrapper = new QueryWrapper<>();
                    groupWrapper.eq("attr_group_id", attrGroupRelation.getAttrGroupId());
                    groupWrapper.select("attr_group_name");
                    AttrGroupEntity attrGroup = attrGroupService.getOne(groupWrapper);
                    attrRespVo.setGroupName(attrGroup.getAttrGroupName());
                }
                // 获取该规格参数对应的 分类名称
                QueryWrapper<CategoryEntity> categoryWrapper = new QueryWrapper<>();
                categoryWrapper.eq("cat_id", attrRespVo.getCatelogId());
                categoryWrapper.select("name");
                CategoryEntity categoryEntity = categoryService.getOne(categoryWrapper);
                if (null != categoryEntity) {
                    attrRespVo.setCatelogName(categoryEntity.getName());
                }
            }
            return attrRespVo;
        }).collect(Collectors.toList());

        pageUtils.setList(voList);

        return pageUtils;
    }

    @Override
    public AttrResponseVo getAttrInfo(Long attrId) {
        // 1.查询规格参数
        AttrEntity attrEntity = this.getById(attrId);

        AttrResponseVo attrRespVo = new AttrResponseVo();
        BeanUtils.copyProperties(attrEntity, attrRespVo);
        // 基本属性
        if (attrEntity.getAttrType() == ProductConstant.AttrEnum.ATTR_TYPE_BASE.getCode()) {
            // 根据规格参数ID获取 参数对应的 分组
            AttrAttrgroupRelationEntity attrGroupRelation = aars.getOne(
                    new QueryWrapper<AttrAttrgroupRelationEntity>()
                            .eq("attr_id", attrRespVo.getAttrId()));
            // 分装分组的名称
            if (null != attrGroupRelation && null != attrGroupRelation.getAttrGroupId()) {
                // 设置分组的ID
                attrRespVo.setAttrGroupId(attrGroupRelation.getAttrGroupId());
                QueryWrapper<AttrGroupEntity> groupWrapper = new QueryWrapper<>();
                groupWrapper.eq("attr_group_id", attrGroupRelation.getAttrGroupId());
                groupWrapper.select("attr_group_name");
                // 获取分组的信息
                AttrGroupEntity attrGroup = attrGroupService.getOne(groupWrapper);
                if (null != attrGroup) {
                    attrRespVo.setGroupName(attrGroup.getAttrGroupName());
                }
            }
        }
        // 封装该规格参数对应的 分类的 树形结构 父 子 子
        Long[] catelogPath = categoryService.getCatelogPath(attrRespVo.getCatelogId());
        attrRespVo.setCatelogPath(catelogPath);

        CategoryEntity entity = categoryService.getById(attrRespVo.getCatelogId());
        if (null != entity) {
            attrRespVo.setCatelogName(entity.getName());
        }
        return attrRespVo;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updateAttr(AttrVo attr) {

        AttrEntity attrEntity = new AttrEntity();
        BeanUtils.copyProperties(attr, attrEntity);
        this.updateById(attrEntity);

        if (attrEntity.getAttrType() == ProductConstant.AttrEnum.ATTR_TYPE_BASE.getCode()) {

            AttrAttrgroupRelationEntity aare = new AttrAttrgroupRelationEntity();
            aare.setAttrId(attr.getAttrId());
            aare.setAttrGroupId(attr.getAttrGroupId());
            // 先查询是否存在该规格参数的分组，
            int count = aars.count(new QueryWrapper<AttrAttrgroupRelationEntity>()
                    .eq("attr_id", attr.getAttrId()));
            // 判断是更新分组还是添加分组
            if (count > 0) {
                aars.update(aare, new QueryWrapper<AttrAttrgroupRelationEntity>()
                        .eq("attr_id", attr.getAttrId()));
            } else {
                aars.save(aare);
            }
        }
    }

    @Override
    public List<AttrEntity> getRelationAttr(Long attrGroupId) {
        // 1.在属性分组和属性关联表中查询所有的属性
        QueryWrapper<AttrAttrgroupRelationEntity> groupWrapper = new QueryWrapper<>();
        groupWrapper.eq("attr_group_id", attrGroupId);

        List<AttrAttrgroupRelationEntity> entities = aars.list(groupWrapper);
        // 2.遍历出属性分组对应的 属性
        List<Long> attrIds = entities.stream().map(
                (entity) -> entity.getAttrId()).collect(Collectors.toList());

        if (null == attrIds && attrIds.size() == 0) {
            return null;
        }
        // TODO 有个bug 当属性分组下没有 规格参数，sql会出现错误
        // 3.获取对应的属性列表
        Collection<AttrEntity> attrEntities = this.listByIds(attrIds);

        return (List<AttrEntity>) attrEntities;
    }

    @Override
    public void deleteRelation(AttrGroupRelationVo[] vos) {

        // 将属性ID 和 对应的 分组ID 封装成 AttrAttrgroupRelationEntity
        List<AttrAttrgroupRelationEntity> entities = Arrays.stream(vos).map((entity) -> {
            AttrAttrgroupRelationEntity relationEntity = new AttrAttrgroupRelationEntity();
            BeanUtils.copyProperties(entity, relationEntity);
            return relationEntity;
        }).collect(Collectors.toList());


        if (null != entities && entities.size() > 0) {
            aars.deleteBatchRelation(entities);
        }
    }

    @Override
    public PageUtils getNoRelationAttr(Map<String, Object> params, Long attrGroupId) {

        // 1.查询对应的分组信息, 当前分组只能关联自己所属的分类里面的所有属性
        AttrGroupEntity attrGroupEntity = attrGroupService.getById(attrGroupId);
        // 2.获取对应的分类ID
        Long catelogId = attrGroupEntity.getCatelogId();
        // 3.获取当前分类下其他的分组
        QueryWrapper<AttrGroupEntity> groupWrapper = new QueryWrapper<>();
        groupWrapper.eq("catelog_id", catelogId);
        List<AttrGroupEntity> groupEntities = attrGroupService.list(groupWrapper);
        // 3.1获取当前分类下其他分组的ID
        List<Long> groupIds = groupEntities.stream().map(
                        groupEntity -> groupEntity.getAttrGroupId())
                .collect(Collectors.toList());
        // 3.2获取其他分组的 关联信息
        List<AttrAttrgroupRelationEntity> attrGroupRelationEntities = aars.list(new QueryWrapper<AttrAttrgroupRelationEntity>()
                .in("attr_group_id", groupIds));
        List<Long> attrIds = attrGroupRelationEntities.stream().map((attrGroupRelationEntity) -> {
            return attrGroupRelationEntity.getAttrId();
        }).collect(Collectors.toList());

        // 4.从当前分类的所有属性中  移除已经 关联的属性；
        QueryWrapper<AttrEntity> wrapper = new QueryWrapper<AttrEntity>()
                .eq("catelog_id", catelogId)
                .eq("attr_type", ProductConstant.AttrEnum.ATTR_TYPE_BASE.getCode());
        // 4.1 排除已经关联的 属性
        if (attrIds != null && attrIds.size() > 0) {
            wrapper.notIn("attr_id", attrIds);
        }
        // 模糊查询
        String key = (String) params.get("key");
        if (!StringUtils.isEmpty(key)) {
            wrapper.and((w) -> {
                w.eq("attr_id", key).or().like("attr_name", key);
            });
        }
        IPage<AttrEntity> page = this.page(new Query<AttrEntity>().getPage(params), wrapper);

        PageUtils pageUtils = new PageUtils(page);

        return pageUtils;
    }

    @Override
    public List<Long> selectSearchAttrs(List<Long> attrIds) {
        // select * from `pms_attr` where in(attr_id = ?) and search_type = 1
        return baseMapper.selectSearchAttrs(attrIds);
    }
}